#pragma once

#include <string>

#include "base/common.h"
#include "util/radix_tree/radix_tree.h"
#include "util/radix_tree/typed_slice_list.h"

namespace hawking {
namespace indexlib {

class VarLenDataIterator {
public:
    VarLenDataIterator(RadixTree* data, TypedSliceList<uint64_t>* offset) :
        data_(data), offset_(offset) {}
    ~VarLenDataIterator() {
        data_ = nullptr;
        offset_ = nullptr;
    }

    void Reset() {
        current_data_ = nullptr;
        current_offset_ = 0;
        cursor_ = -1;
    }

    bool HasNext();
    void Next();
    void CurrentData(uint8_t*& data);
    void CurrentOffset(uint64_t* offset);

    uint64_t Cursor() const {
        return cursor_;
    }

private:
    RadixTree* data_;
    TypedSliceList<uint64_t>* offset_;

    uint8_t* current_data_ = nullptr;
    uint64_t current_offset_ = 0;
    uint64_t cursor_ = -1;
};

class VarLenDataAccessor {
public:
    VarLenDataAccessor() = default;
    ~VarLenDataAccessor() = default;

    void Init(Pool* pool);

    bool AppendValue(const std::string_view& value);
    bool UpdateValue(DocId doc_id, const std::string_view& value);

    bool ReadData(DocId doc_id, uint8_t*& data) const;

    uint64_t GetOffset(DocId doc_id) const {
        return (*offsets_)[doc_id];
    }
    uint64_t GetDocCount() const {
        return offsets_->Size();
    }

    size_t GetAppendDataSize() const {
        return append_data_size_;
    }

    std::shared_ptr<VarLenDataIterator> CreateDataIterator() const;

private:
    bool AppendData_(const std::string_view& value, uint64_t* offset);

    RadixTree* data_ = nullptr;
    TypedSliceList<uint64_t>* offsets_ = nullptr;
    size_t append_data_size_ = 0;
};

}
}